#include <my_head.h>

#define U_R 0400
#define U_W 0200
#define U_X 0100
#define G_R 0040
#define G_W 0020
#define G_X 0010
#define O_R 0004
#define O_W 0002
#define O_X 0001

int main(int argc, const char *argv[]){
    if(2 != argc){
        printf("Usage : %s dir_path\n", argv[0]);
        return -1;
    }
    char buff[1024] = {0};
    struct stat my_stat;
    char pathname[512] = {0};
    char type = 0;
    char u_r = 0;
    char u_w = 0;
    char u_x = 0;
    char g_r = 0;
    char g_w = 0;
    char g_x = 0;
    char o_r = 0;
    char o_w = 0;
    char o_x = 0;
    int nlink = 0;
    char usr_name[32];
    char grp_name[32];
    int size = 0;
    struct tm *p = NULL;
    char data_time[64];
    // 打开目录
    DIR *my_dir = opendir(argv[1]);
    if(NULL == my_dir)
        ERR_LOG("opendir error");
    // 读取目录下的内容
    struct dirent *dp = NULL;
    while(dp = readdir(my_dir)){
        // 过滤隐藏文件
        if('.' == dp->d_name[0]){
            continue;
        }
        // 组装路径和文件名
        sprintf(pathname, "%s/%s", argv[1], dp->d_name);
        // 获取属性
        if(-1 == lstat(pathname, &my_stat))
            ERR_LOG("stat error");
        // 类型
        if(S_ISREG(my_stat.st_mode)){
            type = '-';
        }else if(S_ISDIR(my_stat.st_mode)){
            type = 'd';
        }else if(S_ISLNK(my_stat.st_mode)){
            type = 'l';
        }// 其他类型判断方式同理
        // 权限
        u_r = '-';
        u_w = '-';
        u_x = '-';
        g_r = '-';
        g_w = '-';
        g_x = '-';
        o_r = '-';
        o_w = '-';
        o_x = '-';
        int qx = my_stat.st_mode & 0777;
        if(qx & U_R) u_r = 'r';
        if(qx & U_W) u_w = 'w';
        if(qx & U_X) u_x = 'x';
        if(qx & G_R) g_r = 'r';
        if(qx & G_W) g_w = 'w';
        if(qx & G_X) g_x = 'x';
        if(qx & O_R) o_r = 'r';
        if(qx & O_W) o_w = 'w';
        if(qx & O_X) o_x = 'x';
        // 硬链接数
        nlink = my_stat.st_nlink;
        // 用户名
        strcpy(usr_name, getpwuid(my_stat.st_uid)->pw_name);
        // 组名
        strcpy(grp_name, getgrgid(my_stat.st_gid)->gr_name);
        // 大小
        size = my_stat.st_size;
        // 时间戳
        if(NULL == (p = localtime(&(my_stat.st_mtime))))
            ERR_LOG("localtime error");
        sprintf(data_time, "%2d月  %02d %02d:%02d", \
            p->tm_mon+1, p->tm_mday, p->tm_hour, p->tm_min);
        // 组装属性到数组中
        sprintf(buff, "%c%c%c%c%c%c%c%c%c%c%2d%8s%8s%6d%s %-20s", type, \
            u_r, u_w, u_x, g_r, g_w, g_x, o_r, o_w, o_x,\
            nlink, usr_name, grp_name, size, data_time, dp->d_name);
        // 输出
        printf("%s\n", buff);
    }
    // 关闭目录
    closedir(my_dir);
    return 0;
}